<template>
  <view v-if="result.length || formProps?.formInteractionMode !== 'details'">
    <view v-if="mediaType === 'video'" class="upload-video">
      <view v-if="result[0]" class="edit-video">
        <image
          v-if="!getDisable"
          class="del-icon"
          @click="delItem(0)"
          src="https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/del-icon.png"
          mode="scaleToFill"
        />
        <VideoPlay v-model="getVideoInfo" />
      </view>
      <TButton
        v-else
        text="添加视频"
        icon="&#xe61f;"
        :customStyle="{
          backgroundColor: '#f5f5f5',
          border: '2rpx dashed #dddddd',
          color: '#808080',
        }"
        @click="choose"
      />
    </view>
    <view v-else class="upload-file">
      <template v-for="(v, i) in result" :key="i">
        <view class="upload-file--item">
          <view class="upload-file--item__content">
            <view v-if="v.isErr" class="upload-file--item__mask" @click="reupload(i)">
              <text>重新上传</text>
            </view>
            <image
              v-if="!getDisable"
              src="https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/del-icon.png"
              class="upload-file--item__del"
              @click="delItem(i)"
            />
            <Loading :model-value="!v.isErr && v.progress < 100" text="上传中...">
              <view v-if="mediaType === 'image'" @click="previewImg(i)">
                <TImage
                  :src="v.tempFilePath || v.filePath"
                  width="100%"
                  height="220rpx"
                  borderRadius="10rpx"
                />
              </view>
              <view
                v-if="mediaType === 'doc'"
                class="upload-file--item__file"
                @click="openDocument({ filePath: (v.tempFilePath || v.filePath) as string })"
              >
                <image
                  src="https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/document-icon.png"
                  mode="scaleToFill"
                  class="file-icon"
                />
                <text class="text-overflow-1">{{ v.fileName }}</text>
              </view>
            </Loading>
          </view>
        </view>
      </template>
      <view
        v-if="
          result.length < uploadCount &&
          (formProps?.formInteractionMode !== 'details' || !getDisable)
        "
        class="upload-file--item"
        style="height: 220rpx"
        @click="choose"
      >
        <view class="upload-file--item__content upload-file--add">
          <view class="ali-icon">&#xe61f;</view>
        </view>
      </view>
    </view>
    <view v-if="!getDisable || component === 'Attachment'" class="upload-tips mt-12">
      {{ getProps?.placeholder }}
    </view>
  </view>
  <view v-else class="upload-file"></view>
</template>

<script setup lang="ts">
  import { propTypes } from '@/utils/propTypes';
  import { computed, type PropType, ref, unref, watch, provide } from 'vue';
  import { useFormItem } from '../../hooks/useContext';
  import TImage from '@/components/TImage/index.vue';
  import Loading from '@/components/Loading/index.vue';
  import { type MediaType, useUpload, type DocFileResult } from '@/hooks/core/useUpload';
  import { isArray, isJSON } from '@/utils/is';
  import VideoPlay from '@/components/VideoPlay/index.vue';
  import TButton from '@/components/TButtonGroup/TButton.vue';

  const props = defineProps({
    modelValue: [String, Array],
    limit: propTypes.number.def(1),
    disabled: propTypes.bool.def(false),
    mediaType: {
      type: String as PropType<MediaType>,
      default: 'image',
    },
  });

  const emit = defineEmits(['update:modelValue', 'updateResult']);

  const { getProps, setFormModel, formProps, component, FormItem } = useFormItem(props);

  const uploadCount = computed(() => {
    if (props.mediaType === 'video' || unref(getProps)?.isCrop) return 1;
    return getProps.value.limit || props.limit;
  });

  const {
    result,
    successResult,
    chooseFile,
    delResultItem,
    reupload,
    addResultItem,
    openDocument,
  } = useUpload({
    count: uploadCount,
    isUploadVideoCover: true,
    isCrop: unref(getProps)?.isCrop,
    cropOptions: unref(getProps)?.cropOptions,
  });

  function choose() {
    if (getDisable.value) return;
    const { mediaType } = props;
    chooseFile({
      mediaType,
    });
  }

  const isFirstLoad = ref(false);
  watch(
    [() => getProps.value.modelValue, () => props.modelValue],
    ([v1, v2]) => {

      let val = (v1 || v2) as string | string[];

      if (val && val.length) {
        if (!isArray(val)) {
          val = isJSON(val) ? [val] : val.split(',');
        }
        setDefaultVal(val);
      }
    },
    {
      immediate: true,
      deep: true,
    },
  );

  function setDefaultVal(val: string[]) {
    for (let index = 0; index < val.length; index++) {
      const v = val[index];
      if (!isJSON(v)) {
        addResultItem({
          filePath: v,
          progress: 100,
        });
      } else {
        const item = isJSON(v) as DocFileResult;
        addResultItem({
          filePath: item.url,
          fileSize: item.size,
          fileName: item.name,
          extension: item.fileType,
          progress: 100,
        });
      }
    }
  }

  watch(
    successResult,
    (val) => {
      isFirstLoad.value = true;
      updateFormVals();
    },
    { deep: true },
  );

  const getDisable = computed(() => {
    return getProps.value.disabled;
  });

  /** 预览图片列表 */
  function previewImg(index: number) {
    uni.previewImage({
      urls: result.value.map((v) => {
        return v.tempFilePath || (v.filePath as string);
      }),
      current: index,
    });
  }

  const getVideoInfo = computed(() => {
    const { filePath, tempFilePath } = result.value[0] || {};
    return {
      videoUrl: tempFilePath || filePath,
      coverUrl: '',
    };
  });

  function delItem(index: number) {
    delResultItem(index);
    updateFormVals();
  }

  function updateFormVals() {
    let vals: Array<string> | string;
    if (props.mediaType === 'doc') {
      vals = result.value.map((v) =>
        JSON.stringify({
          name: v.fileName,
          url: v.filePath,
          size: v.fileSize,
          fileType: v.extension,
        }),
      );
    } else {
      vals = result.value.map((v) => v.filePath).join(',');
    }
    setFormModel(vals);
    emit('update:modelValue', vals);
    emit('updateResult', unref(result));
  }

  provide('isPlayVideo', null);
</script>

<style lang="scss" scoped>
  .upload-video {
    width: 100%;
    flex: 1;
    margin-bottom: 10rpx;
    .edit-video {
      position: relative;
      .del-icon {
        position: absolute;
        right: -10rpx;
        top: -10rpx;
        width: 32rpx;
        height: 32rpx;
        z-index: 2;
      }
    }
  }
  .upload-file {
    width: 100%;
    flex: 1;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-column-gap: 16rpx;
    grid-row-gap: 16rpx;
    &:empty::before {
      content: '暂无内容';
      color: gray;
    }
    &--item {
      &__content {
        width: 100%;
        height: 100%;
        margin: 0 auto;
        border: 1px solid #f5f5f5;
        border-radius: 10rpx;
        position: relative;
      }
      &__file {
        width: 100%;
        height: 220rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        color: #808080;
        font-size: 24rpx;
        .file-icon {
          width: 140rpx;
          height: 140rpx;
          margin-bottom: 10rpx;
        }
      }
      &__del {
        color: #dddddd;
        width: 50rpx;
        height: 50rpx;
        position: absolute;
        right: -15rpx;
        top: -20rpx;
        z-index: 1;
      }
      &__mask {
        width: 100%;
        height: 100%;
        background-color: rgba($color: #000000, $alpha: 0.6);
        position: absolute;
        left: 0;
        top: 0;
        z-index: 1;
        border-radius: 10rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
      }
    }
    &--add {
      background-color: #f5f5f5;
      border: 1px solid transparent;
      display: flex;
      align-items: center;
      justify-content: center;
      .ali-icon {
        color: #aaabab;
        font-size: 72rpx;
      }
    }
  }
  .upload-tips {
    color: #aaabab;
    font-size: 24rpx;
  }
</style>
